/*   The MIT License
 *   
 *   Carina Engine
 *   Copyright (c) 2009 2010 2011 2012 Zdravko Velinov
 *   
 *   Permission is hereby granted, free of charge, to any person obtaining a copy
 *   of this software and associated documentation files (the "Software"), to deal
 *   in the Software without restriction, including without limitation the rights
 *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *   copies of the Software, and to permit persons to whom the Software is
 *   furnished to do so, subject to the following conditions:
 *
 *   The above copyright notice and this permission notice shall be included in
 *   all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *   THE SOFTWARE.
 */

#ifndef SETTINGS_FILE_HH_
#define SETTINGS_FILE_HH_

#include "carina/common/containers.hh"
#include "carina/common/logging.hh"

namespace Carina
{
namespace AST
{
template<class T> struct NodeT;
typedef NodeT<void> Node;
class ListElement;
typedef ListElement List;
}
    
//! Contains information about all separate rendering windows.
class ContextSettings
{
    string      m_Name;     //!< Context's name.
    unsigned    m_Width,    //!< Window width.
                m_Height,   //!< Window height.
                m_MSAA;     //!< The number of samples. When MSAA is 1, it is disabled.
public:
    ContextSettings();

    ContextSettings(const string& name);

    //! Loads the settings associated with this context from the specified XML element.
    void _load(const AST::List* ctx);

    //! Saves the settings in this object for the specified XML element.
    AST::NodeT<AST::List>* _save(AST::NodeT<AST::List>* ctx) const;

    //! Sets the width of the window associated with this context.
    void setWidth(size_t width);

    //! Returns the width of the window associated with this context.
    size_t getWidth() const;

    //! Sets the height of the window associated with this context.
    void setHeight(size_t height);

    //! Returns the height of the window associated with this context.
    size_t getHeight() const;

    void setName(const string& name);

    string getName() const;

    //! Sets the number of samples used for MSAA. 1 sample disables MSAA.
    void setMSAA(size_t samples = 1);

    //! Returns the number of samples used for MSAA. 1 sample means that this feature is disabled.
    size_t getMSAA() const;

};

//! Contains settings used by the graphics engine.
class SettingsFile
{
    string                      m_RendererName, //!< The current rendering back-end, such as OpenGL or DirectX.
                                m_LogFilename;  //!< The path to the logging file.
    LoggingLevel                m_LoggingLevel; //!< The minimum logging information which is going to be written by the logger.
    DataVector<string>          m_Resources;    //!< List of all resource paths.
    DataVector<ContextSettings> m_Contexts;     //!< List of all contexts.
public:
    //! Constructor.
    SettingsFile();

    //! Loads the settings from the specified file.
    bool load(const string& filename=SettingsFile::getDefaultConfig());

    //! Saves the settings to the specified file. 
    bool save(const string& filename=SettingsFile::getDefaultConfig()) const;

    //! Returns the default configuration file location.
    static string getDefaultConfig();

    //! Clears the contents of this object.
    void clear();

    //! Sets the rendering back-end, such as OpenGL or DirectX.
    void setRenderer(const string& str);

    //! Returns the rendering back-end.
    string getRenderer() const;

    //! Sets the path to the logging file.
    void setLogFile(const string& filename);

    //! Sets the minimum information that must be logged.
    void setLogLevel(LoggingLevel log_level);
    
    /*! \brief Sets the path to the logging file to the default one. This function ensures that even if it gets
     *         changed, the engine will pick up the new one.
     */
    void setDefaultLogFile();

    //! Adds a resource path.
    void addResource(const string& str);

    //! Removes a resource with the specified path.
    void removeResource(const string& str);

    //! Returns the resource path with the specified index.
    string getResource(size_t idx) const;

    //! Returns the number of resource paths.
    size_t getResourceCount() const;

    //! Returns the current logging file.
    string getLogFile() const;

    //! Returns the minimum logging information.
    LoggingLevel getLogLevel() const;

    //! Returns whether the current logging file is the default one.
    bool isDefaultLogFile() const;

    //! Returns the default logging file path.
    static string getDefaultLogFile();

    void addContext(const string& name);

    void deleteContext(const string& name);

    ContextSettings& lastContext();

    //! Returns the settings for the context that is associated with the specified index.
    ContextSettings& getContext(size_t ctx_idx);

    ContextSettings& getContext(const string& name);

    //! Returns the number of contexts.
    size_t getContextCount();
};
}

#endif /* SETTINGS_FILE_HH_ */
